﻿using System;
using System.Collections.Generic;
using UnityEngine;

public class ElementHolder : MonoBehaviour, IElementHolder
{
    // 附着元素
    private readonly Dictionary<string, IElementAura> _elementAuras = new()
    {
        ["火"] = new ElementAura(ElementType.Fire),
        ["水"] = new ElementAura(ElementType.Water),
        ["草"] = new ElementAura(ElementType.Grass),
        ["雷"] = new ElementAura(ElementType.Electric),
        ["冰"] = new ElementAura(ElementType.Ice),
    };

    // 元素反应
    private readonly List<IElementReaction> _elementReactions = new();

    // 元素状态
    private readonly List<IElementState> _elementStates = new();

    public GameObject Owner => gameObject;

    private void Awake()
    {
        _elementAuras["激化"] = new QuickenAura();
        _elementAuras["燃烧"] = new BurningAura(this);
        _elementAuras["冻结"] = new FreezeAura(this);

        var electroChargedState = new ElementElectroChargedState(this);
        _elementStates.Add(electroChargedState);
        var swirlState = new ElementSwirlState();
        _elementStates.Add(swirlState);

        // todo: 元素反应有优先级，需要进一步研究机制
        _elementReactions.Add(new ElementFrozenBroken(this));
        _elementReactions.Add(new ElementOverloaded(this));
        _elementReactions.Add(new ElementVaporize(this));
        _elementReactions.Add(new ElementMelt(this));
        _elementReactions.Add(new ElementSuperconduct(this));
        _elementReactions.Add(new ElementQuicken(this));
        _elementReactions.Add(new ElementFrozen(this));
        _elementReactions.Add(new ElementBloom(this));
        _elementReactions.Add(new ElementBurning(this));
        _elementReactions.Add(new ElementElectroCharged(this, electroChargedState));
        _elementReactions.Add(new ElementSwirl(this, swirlState));
        _elementReactions.Add(new ElementCrystallize(this));
    }

    private void Update()
    {
        foreach (var elementState in _elementStates)
        {
            elementState.Update(Time.deltaTime);
        }

        foreach (var aura in _elementAuras.Values)
        {
            aura.Update(Time.deltaTime);
        }
    }

    public string ElementTypeToName(ElementType elementType)
    {
        return elementType switch
        {
            ElementType.Fire => "火",
            ElementType.Water => "水",
            ElementType.Grass => "草",
            ElementType.Electric => "雷",
            ElementType.Wind => "风",
            ElementType.Ice => "冰",
            ElementType.Rock => "岩",
            _ => throw new ArgumentOutOfRangeException(nameof(elementType), elementType, null)
        };
    }

    public IElementAura GetElementAura(string auraName)
    {
        return _elementAuras[auraName];
    }

    public IGeneralElementAura GetGeneralElementAura(ElementType elementType)
    {
        return elementType switch
        {
            ElementType.Fire => new GeneralFireAura(this),
            ElementType.Water => new GeneralAura(GetElementAura("水")),
            ElementType.Grass => new GeneralGrassAura(this),
            ElementType.Electric => new GeneralAura(GetElementAura("雷")),
            ElementType.Ice => new GeneralIceAura(this),
            _ => throw new ArgumentOutOfRangeException(nameof(elementType), elementType, null)
        };
    }

    public void ElementReaction(TriggerElementData triggerElementData)
    {
        Debug.Log($"元素反应: {Owner} | {triggerElementData.ElementType} | {triggerElementData.Gauge}");
        
        foreach (var elementReaction in _elementReactions)
        {
            if (triggerElementData.Gauge <= 0f) // 触发元素消耗完
            {
                return;
            }

            elementReaction.Reaction(triggerElementData);
        }

        if (!triggerElementData.IsTriggered &&
            triggerElementData.Gauge > 0f &&
            triggerElementData.ElementType is not (ElementType.Wind or ElementType.Rock))
        {
            _elementAuras[ElementTypeToName(triggerElementData.ElementType)]
                .Attach(triggerElementData.Gauge, triggerElementData.Source);
        }
    }
}